-
Notifications
You must be signed in to change notification settings - Fork 68
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
two small changes to support native hardware features in embedded (for example hardware DMA and CRC in STM32) #55
base: master
Are you sure you want to change the base?
Conversation
…ving packets using DMA in asynchronous mode
in HAL STM functions configurations are declared as __Weak to make override possible in case of other implementations in user file #if defined (__ARMCC_VERSION) && (__ARMCC_VERSION >= 6010050) /* ARM Compiler V6 / |
or do we need any other way to use our crc16 function |
Hi, thanks for the PR. I don't know if the time spent on calculating the CRC in a typical modbus application justifies doing it via DMA, but I think giving the user the possibility to override the CRC calc function won't hurt. The only thing I would change is, instead of redefining the symbol, using the already established system of defining a function pointer inside the Regarding the STM32 example, can you provide a way for the user to build it? I know on micros it's a bit messy to setup a shareable build environment, but even a simple makefile could be enough. Maybe one where the user must define the path to the STM32 SDK (which I guess should be the only thing needed to build this) |
this helps to reduce the cost of the product. you can take a cheaper processor that can handle processing, for example, six streams (ports) at once at high speed (modbus gateway). I will make a ready-made example with a makefile a little later. |
Implemented in #64 |
Just for other people's reference, here's how I implemented hardware CRC calculation on my STM32H723ZG: CRC_HandleTypeDef hcrc;
hcrc.Instance = CRC;
hcrc.Init.DefaultPolynomialUse = DEFAULT_POLYNOMIAL_DISABLE;
hcrc.Init.DefaultInitValueUse = DEFAULT_INIT_VALUE_DISABLE;
hcrc.Init.GeneratingPolynomial = 0x8005;
hcrc.Init.CRCLength = CRC_POLYLENGTH_16B;
hcrc.Init.InitValue = 0xFFFF;
hcrc.Init.InputDataInversionMode = CRC_INPUTDATA_INVERSION_BYTE;
hcrc.Init.OutputDataInversionMode = CRC_OUTPUTDATA_INVERSION_ENABLE;
hcrc.InputDataFormat = CRC_INPUTDATA_FORMAT_BYTES;
if (HAL_CRC_Init(&hcrc) != HAL_OK) {
Error_Handler();
} uint16_t modbusHardwareCRC(const uint8_t* data, uint32_t length, void* arg) {
const uint16_t crc = HAL_CRC_Calculate(&hcrc, (uint32_t*) data, length);
return ((uint16_t) (crc << 8)) | ((uint16_t) (crc >> 8));
} In my testing, hardware CRC was ~10 times faster than software CRC. The only drawback of hardware CRC is that it needs to be protected by a mutex if multiple tasks need it, which slows things down significantly. Here's my workaround, which is still, on average, ~5 times faster than software CRC: uint16_t modbusHardwareCRC(const uint8_t* data, uint32_t length, void* arg) {
if (osMutexAcquire(crcMutex, 0UL) == osOK) {
if (HAL_CRC_GetState(&hcrc) == HAL_CRC_STATE_READY) {
const uint16_t crc = HAL_CRC_Calculate(&hcrc, (uint32_t*) data, length);
osMutexRelease(crcMutex);
return ((uint16_t) (crc << 8)) | ((uint16_t) (crc >> 8));
}
osMutexRelease(crcMutex);
return nmbs_crc_calc(data, length, arg);
}
return nmbs_crc_calc(data, length, arg);
} I got Modbus over TCP working with the lwIP network stack of the STM32. I'll be testing UART with DMA soon. I'll see what I can share. So far, the library has been rock solid during testing. |
@marcocipriani01 yes, an STM32 example with lwIP and a custom CRC function would be very useful |
In order not to send data from one buffer to another, but to immediately receive data where it is needed (for example, in DMA mode), the buf_rec index is needed in structure nmbs_t.msg, it is used in the nmbs_platform_conf.read function
and nmbs_crc_calc requires the __weak attribute so that this function can be replaced with hardware calculation of the modbus CRC, a polynomial for which is also available in some embedded systems, including STM32
code examples for stm32 using HAL are attached